package com.baijiayun.liveuibase.toolbox.zxyb

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Build
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.baijiahulian.common.permission.AppPermissions
import com.baijiayun.livecore.context.LPConstants
import com.baijiayun.livecore.context.LiveRoom
import com.baijiayun.livecore.utils.LPLogger
import com.baijiayun.livecore.utils.LPRxUtils
import com.baijiayun.livecore.utils.ToastCompat
import com.baijiayun.liveuibase.R
import com.baijiayun.liveuibase.widgets.dialog.BluetoothDeviceDialog
import com.baijiayun.liveuibase.widgets.dialog.CommonDialog
import com.zxyb.zxybbaselib.ble.entity.BleDevice
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable

/**
 * Created by pengwenjian on 2021/6/19
 * Describe: 手写板包装类,大小班ui基本相同，公用
 */
class WritingboardWrapper(private val context: AppCompatActivity, private val liveRoom: LiveRoom, private val icon: ImageView) {
    var connectStateCallback: ConnectStateCallback? = null
    var deviceScanCallback: DeviceScanCallback? = null
    var config: Config? = null
        set(value) {
            field = value
            initView()
        }
    private var permissionDisposable: Disposable? = null
    private var disposables = CompositeDisposable()
    private val bleDialog by lazy {
        BluetoothDeviceDialog(liveRoom)
    }

    private fun checkBluetoothPermission(): Boolean {
        context.let {
            if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(it, Manifest.permission.ACCESS_FINE_LOCATION)) {
                return true
            } else {
                LPRxUtils.dispose(permissionDisposable)
                permissionDisposable = Observable.just("").compose<Boolean>(AppPermissions.newPermissions(it)
                        .ensure(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_ADMIN))
                        .subscribe {
                            showBleDialogWithPermission()
                        }
            }
        }
        return false
    }

    @SuppressLint("MissingPermission")
    private fun checkBluetoothAvailable(): Boolean {
        var bluetoothAvailable: Boolean
        context.run {
            bluetoothAvailable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                val alm = ContextCompat.getSystemService(this, LocationManager::class.java)
                alm?.isProviderEnabled(LocationManager.GPS_PROVIDER) == true
            } else {
                true
            }
            if (!BluetoothAdapter.getDefaultAdapter().isEnabled) {
                CommonDialog(this, CommonDialog.ChoiceMode.Double_Blue)
                        .setMainDisplayText(if (bluetoothAvailable) resources.getString(R.string.base_live_ble_open_tips)
                        else resources.getString(R.string.base_live_ble_gps_open_tips))
                        .setPositive(
                                resources.getString(R.string.base_live_i_know_ok)
                        ) { dialog, _ ->
                            dialog.dismiss()
                        }
                        .show()
                bluetoothAvailable = false
            } else {
                if (!bluetoothAvailable) {
                    CommonDialog(this, CommonDialog.ChoiceMode.Double_Blue)
                            .setMainDisplayText(resources.getString(R.string.base_live_gps_open_tips))
                            .setPositive(
                                    resources.getString(R.string.base_live_i_know_ok)
                            ) { dialog, _ ->
                                dialog.dismiss()
                            }
                            .show()
                }
            }
        }
        return bluetoothAvailable
    }

    @SuppressLint("MissingPermission")
    fun showBleDialogWithPermission() {
        if (checkBluetoothAvailable() && checkBluetoothPermission()) {
            showBluetoothDevicesDialog()
        }
    }

    private fun showBluetoothDevicesDialog() {
        context.run {
            if (bleDialog.isAdded) {
                bleDialog.setData(liveRoom.zxybvm.recentBleDevices)
                        .refresh()
            } else {
                bleDialog.setData(liveRoom.zxybvm.recentBleDevices)
                        .show(context.supportFragmentManager, "BluetoothDeviceDialog")
            }
        }
    }

    init {
        initZXYBSDK()
    }

    private fun initView() {
        if (config == null) {
            return
        }
        config?.run {
            if (bleConnectResId == -1 || bleDisconnectResId == -1 || bleSleepResId == -1
                    || usbConnectResId == -1 || usbDisconnectResId == -1 || usbSleepResId == -1) {
                return
            }
        }
        when (liveRoom.zxybvm.connectType) {
            LPConstants.ZXYBConnectType.TYPE_BLE -> {
                icon.setImageResource(config!!.bleDisconnectResId)
            }
            LPConstants.ZXYBConnectType.TYPE_SERIALPORT, LPConstants.ZXYBConnectType.TYPE_USB -> {
                icon.setImageResource(config!!.usbDisconnectResId)
            }
        }
        icon.setOnClickListener {
            if (liveRoom.zxybvm.connectType == LPConstants.ZXYBConnectType.TYPE_BLE) {
                when (liveRoom.zxybvm.connectStatus) {
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SUCCESS -> {
                        context.run {
                            CommonDialog(this, CommonDialog.ChoiceMode.Double_Blue)
                                    .setMainDisplayText(resources.getString(R.string.base_live_ble_disconnect_by_hand))
                                    .setPositive(
                                            resources.getString(R.string.base_confirm)
                                    ) { dialog, _ ->
                                        dialog?.dismiss()
                                        liveRoom.zxybvm.closeZXYB()
                                        config?.bleDisconnectResId?.run { icon.setImageResource(this) }
                                    }.setNegative(
                                            resources.getString(R.string.base_cancel)
                                    ) { dialog, _ -> dialog?.dismiss() }
                                    .show()
                        }
                    }
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_CONNECTING -> {
                        //连接中不反应
                    }
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SLEEP -> {
                        ToastCompat.showToast(
                                context,
                                context.getString(R.string.base_live_usb_awake_tips),
                                Toast.LENGTH_SHORT
                        )
                    }
                    else -> {
                        showBleDialogWithPermission()
                    }
                }
            } else {
                when (liveRoom.zxybvm.connectStatus) {
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SLEEP -> {
                        when (liveRoom.zxybvm.connectType) {
                            LPConstants.ZXYBConnectType.TYPE_SERIALPORT -> {
                                liveRoom.zxybvm.setWorkState(true)
                            }
                            LPConstants.ZXYBConnectType.TYPE_USB -> {
                                ToastCompat.showToast(
                                        context,
                                        context.getString(R.string.base_live_usb_awake_tips),
                                        Toast.LENGTH_SHORT
                                )
                            }
                        }
                    }
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SUCCESS -> {
                        context.run {
                            CommonDialog(this, CommonDialog.ChoiceMode.Double_Blue)
                                    .setMainDisplayText(resources.getString(R.string.base_live_usb_disconnect_by_hand))
                                    .setPositive(
                                            resources.getString(R.string.base_confirm)
                                    ) { dialog, _ ->
                                        dialog?.dismiss()
                                        liveRoom.zxybvm.closeZXYB()
                                        config?.bleConnectResId?.run { icon.setImageResource(this) }
                                    }.setNegative(
                                            resources.getString(R.string.base_cancel)
                                    ) { dialog, _ -> dialog?.dismiss() }
                                    .show()
                        }
                    }
                    LPConstants.ZXYBConnectStatus.CONNECT_STATUS_UNKOWN -> {
                        liveRoom.zxybvm.connectZXYB()
                    }
                }
            }
        }
    }

    private fun initZXYBSDK() {
        disposables.add(liveRoom.zxybvm.observableOfScanStatus
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (it) {
                        deviceScanCallback?.onStartScan()
                    } else {
                        deviceScanCallback?.onStopScan()
                    }
                })
        disposables.add(liveRoom.zxybvm.observableOfScanDevice
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    LPLogger.d("zxyb-ble", "onScanDevice name=${it.name}, address=${it.address}")
                    deviceScanCallback?.onScanDevice(it)
                })

        disposables.add(liveRoom.zxybvm.observableOfConnectStatus
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    LPLogger.d(
                            "zxyb-ble", "connectStatus=${it}"
                    )
                    if (config == null) {
                        return@subscribe
                    }
                    config?.run {
                        if (bleConnectResId == -1 || bleDisconnectResId == -1 || bleSleepResId == -1
                                || usbConnectResId == -1 || usbDisconnectResId == -1 || usbSleepResId == -1) {
                            return@subscribe
                        }
                    }
                    onConnectStatus(it)
                    connectStateCallback?.onConnectState(it)
                })
    }

    private fun onConnectStatus(connectStatus: LPConstants.ZXYBConnectStatus) {
        when (connectStatus) {
            LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SUCCESS -> {
                icon.setImageResource(if (liveRoom.zxybvm.connectType == LPConstants.ZXYBConnectType.TYPE_BLE) config!!.bleConnectResId else config!!.usbConnectResId)
                ToastCompat.showToast(
                        context,
                        context.getString(R.string.base_live_writing_board_connect_success),
                        Toast.LENGTH_SHORT
                )
            }
            LPConstants.ZXYBConnectStatus.CONNECT_STATUS_FAIL -> {
                if (liveRoom.zxybvm.connectType == LPConstants.ZXYBConnectType.TYPE_BLE) {
                    context.run {
                        CommonDialog(this, CommonDialog.ChoiceMode.Double_Blue)
                                .setMainDisplayText(resources.getString(R.string.base_live_writing_board_lose_connection))
                                .setSubtitleDisplayText(resources.getString(R.string.base_live_writing_board_lose_connection_tips))
                                .setSubtitleTextColor(
                                        ContextCompat.getColor(this, R.color.base_live_bluetooth_disconnected_tips)
                                )
                                .setNegative(
                                        resources.getString(R.string.base_cancel)
                                ) { dialog, _ -> dialog.dismiss() }
                                .setPositive(
                                        resources.getString(R.string.base_live_reconnect)
                                ) { _, _ ->
                                    showBluetoothDevicesDialog()
                                }
                                .show()
                    }
                }
            }
            LPConstants.ZXYBConnectStatus.CONNECT_STATUS_SLEEP -> {
                icon.setImageResource(if (liveRoom.zxybvm.connectType == LPConstants.ZXYBConnectType.TYPE_BLE) config!!.bleSleepResId else config!!.usbSleepResId)
                ToastCompat.showToast(
                        context,
                        context.getString(R.string.base_live_usb_awake_tips),
                        Toast.LENGTH_LONG
                )
            }
            else -> {
                icon.setImageResource(if (liveRoom.zxybvm.connectType == LPConstants.ZXYBConnectType.TYPE_BLE) config!!.bleDisconnectResId else config!!.usbDisconnectResId)
            }
        }
    }

    fun onDestroy() {
        LPRxUtils.dispose(disposables)
    }

    class Config {
        var bleConnectResId: Int = -1
        var bleDisconnectResId: Int = -1
        var bleSleepResId: Int = -1
        var usbConnectResId: Int = -1
        var usbDisconnectResId: Int = -1
        var usbSleepResId: Int = -1
    }

    interface ConnectStateCallback {
        fun onConnectState(connectState: LPConstants.ZXYBConnectStatus)
    }

    interface DeviceScanCallback {
        fun onStartScan()
        fun onScanDevice(bleDevice: BleDevice?)
        fun onStopScan()
    }
}